import React from 'react';
import classnames from 'classnames';
import ReChip from '../ReChip';

import './index.less';

export default class view extends React.Component {
    static propTypes = {
        name: React.PropTypes.string,
        value: React.PropTypes.any,
        options: React.PropTypes.array,
        allowCreate: React.PropTypes.bool,
        valueMaxCounts: React.PropTypes.number,
        valueMaxLength: React.PropTypes.number,
        onSelect: React.PropTypes.func,
        onDelete: React.PropTypes.func,
        onChange: React.PropTypes.func,
        onError: React.PropTypes.func,
        onInputChange: React.PropTypes.func,
        placeholder: React.PropTypes.string,
        label: React.PropTypes.string,
        isLabel: React.PropTypes.bool,
    };

    static defaultProps = {
        value: [],
        options: [],
        inputMinWidth: 2,
        allowCreate: true,
        allowCreateLabelPrefix: '',
        valueMaxCounts: Infinity,
        valueMaxLength: Infinity,
        label: 'default',
        isLabel: true,
        onChange: () => {
        },
        onError: () => {
        },

    }

    constructor(props, context) {
        super(props, context);
        // let options = [
        //         { label: 'apple', value: 'apple' },
        //         { label: 'google', value: 'google' },
        //         { label: 'facebook', value: 'facebook' },
        //         { label: 'amazon', value: 'amazon' },
        //         { label: 'netflix', value: 'netflix' },
        //         { label: 'microsoft', value: 'microsoft' },
        //         { label: 'alibaba', value: 'alibaba' },
        //         { label: 'tencent', value: 'tencent' },
        //         { label: 'baidu', value: 'baidu' },
        // ];
        this.state = {
            input: '',
            value: props.value,
            options: props.options,
            results: props.options,
            inputWidth: props.inputMinWidth,
            valueMaxCounts: props.valueMaxCounts,
            valueMaxLength: props.valueMaxLength,
            allowCreateLabelPrefix: props.allowCreateLabelPrefix || '',
            activeIndex: -1,
            showOptions: false,
            shouldTriggerBlur: true,
            isNoOptionMatch: false,
            isExists: false,
            placeholder: props.placeholder,
            isUpdateInputWidth: false,
            focus: false,
        };

    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.value.length > 0) {
            this.setState({
                inputWidth: 2,
                placeholder: '',
                input: '',
                value: nextProps.value,
                options: nextProps.options,
                isUpdateInputWidth: true
            });
        } else {
            this.setState({
                input: '',
                value: nextProps.value,
                options: nextProps.options,
                inputWidth: this.refs.ROOT.clientWidth - 10,
                isUpdateInputWidth: false
            });
        }
    }

    componentWillMount() {
        this._isMounted = true;

    }

    componentDidMount() {
        this._updatePlaceholder();
        // this._updateInputWidth();
    }

    componentDidUpdate() {
        // this._updateInputWidth();
    }

    componentWillUnmount() {
        this._isMounted = false;
    }

    renderSelectedValues() {
        let {focus} = this.state;
        return (
            <div className={focus ? 'wrapper focus' : 'wrapper'}>
                {this.state.value.map((v, i) =>
                    <ReChip key={i} label={v.label} onDelete={this.handleValueRemove.bind(this, i)}/>
                )}
                {this.renderInput()}
                {(this.state.value.length > 0 || !!this.state.input) &&
                <span className="desc">{this.props.descText}</span>}
            </div>
        );
    }

    renderInput() {
        return (
            <div className="input-wrapper">
                <input
                    className="input"
                    type="text"
                    ref="INPUT"
                    maxLength={this.props.valueMaxLength}
                    value={this.state.input}
                    onFocus={this.handleInputFocus.bind(this)}
                    onBlur={this.handleInputBlur.bind(this)}
                    onChange={this.handleInputChange.bind(this)}
                    onKeyDown={this.handleInputKeyDown.bind(this)}
                    placeholder={this.state.placeholder}
                />
                <div className="sizer" ref="SIZER">{this.state.input}</div>
            </div>
        );
    }

    renderOptions() {
        return (
            <ul className="options"
                style={{
                    top: this.refs.ROOT.clientHeight
                }}>
                {!this.props.allowCreate && this.state.isNoOptionMatch && this.state.input &&
                <li className="option">{$$.LN.WIDGETS_SELECT_NO_OPTION_MATCH}</li>}
                {this.props.allowCreate && this.state.isExists &&
                <li className="option">{this.state.input} {$$.LN.WIDGETS_SELECT_VALUE_EXISTS}</li>}
                {this.state.results.map((v, i) =>
                    <li key={i}
                        className={classnames({
                            'option': true,
                            'is-focus': this.state.activeIndex === i
                        })}
                        onClick={this.handleOptionSelect.bind(this, v)}
                        onMouseOver={this.handleOptionHover.bind(this, i)}>
                        {v.label}
                    </li>
                )}
            </ul>
        );
    }

    _onSelect(option) {
        this.props.onSelect && this.props.onSelect(option);
    }

    _onDelete(option) {
        this.props.onDelete && this.props.onDelete(option);
    }

    _onChange() {
        this.props.onChange && this.props.onChange(this.state.value);
    }

    _onInputChange() {
        this.props.onInputChange && this.props.onInputChange(this.state.input);
    }

    _filterOptions() {
        let results = this.state.options
        .filter(x => this.state.value.filter(y => y.value === x.value).length === 0)
        .filter(v => v.label.indexOf(this.state.input) !== -1 || v.value.indexOf(this.state.input) !== -1);

        let isExists = this.state.value.filter(v => v.value === this.state.input).length > 0;
        let isNoOptionMatch = results.length === 0;

        if (this.props.allowCreate &&
            this.state.input.length <= this.state.valueMaxLength &&
            this.state.value.length < this.state.valueMaxCounts &&
            !isExists &&
            isNoOptionMatch &&
            this.state.input
        ) {
            results = [{label: this.state.allowCreateLabelPrefix + this.state.input, value: this.state.input}];
        }

        this.setState({
            results,
            isNoOptionMatch,
            isExists,
            activeIndex: results.length === 0 ? -1 : 0
        }, () => {
            // this._updateError();
        });
    }

    _parseSelectedOption(option) {
        // 去掉选项列表中的 '创建 '
        return this.state.isNoOptionMatch
            ? Object.assign({}, option, {label: option.label.substring(this.state.allowCreateLabelPrefix.length)})
            : option;
    }

    _updateError() {
        if (!this.props.allowCreate && this.state.isNoOptionMatch && this.state.input) {
            this.props.onError({type: 0, err: $$.LN.WIDGETS_SELECT_NO_OPTION_MATCH});
        }

        if (this.props.allowCreate && this.state.isExists) {
            this.props.onError({type: 1, err: `${this.state.input} ${$$.LN.WIDGETS_SELECT_VALUE_EXISTS}`});
        }

        if (this.state.input.length > this.state.valueMaxLength) {
            this.props.onError({
                type: 1,
                err: $$.LN.WIDGETS_SELECT_VALUE_MAX_LENGTH_TIPS.replace(/\$value/, this.state.valueMaxLength)
            });
        } else {
            this.props.onError({type: 1, err: ''});
        }
    }

    _updateInputWidth() {
        if (!this._isMounted || typeof this.refs.SIZER.scrollWidth === 'undefined') {
            return;
        }


        let inputWidth = this.refs.SIZER.scrollWidth;

        if (inputWidth < this.props.inputMinWidth) {
            inputWidth = this.props.inputMinWidth;
        }

        if (this.state.inputWidth !== inputWidth && this.state.isUpdateInputWidth) {
            this.setState({inputWidth});
        }

    }

    _updatePlaceholder() {
        if (this.state.value.length > 0) {
            this.setState({
                inputWidth: 2,
                placeholder: '',
                isUpdateInputWidth: true
            });
        } else {
            this.setState({
                inputWidth: this.refs.ROOT.clientWidth - 10,
                placeholder: this.props.placeholder,
                isUpdateInputWidth: false
            });
        }
    }

    handleRootClick() {
        this.refs.INPUT.focus();
    }

    handleOptionSelect(option) {
        option = this._parseSelectedOption(option);
        let value = this.state.value.concat(option);
        this.setState({value, input: ''}, () => {
            this._onSelect(option);
            this._onChange();
            this._updatePlaceholder();
        });
    }

    handleOptionHover(index) {
        this.setState({activeIndex: index});
    }

    handleValueRemove(index) {
        let option = this.state.value[index];
        let value = this.state.value.slice();
        value.splice(index, 1);
        this.setState({value}, () => {
            this._onDelete(option);
            this._onChange();
            this._updatePlaceholder();
        });
    }

    handleMouseEnter() {
        this.setState({shouldTriggerBlur: false});
    }

    handleMouseLeave() {
        this.setState({shouldTriggerBlur: true});
    }

    handleInputFocus() {
        this.setState({showOptions: true, focus: true}, this._filterOptions);
        this.refs.ROOT.className += ' focus-style';
    }

    handleInputBlur() {
        this.state.shouldTriggerBlur && this.setState({showOptions: false, activeIndex: -1, focus: false});
        this.refs.ROOT.className = this.refs.ROOT.className.replace(' focus-style', '');
    }

    handleInputChange(e) {
        this.setState({input: e.target.value}, () => {
            this._onInputChange();
            this._filterOptions();
        });
    }

    handleInputKeyDown(e) {

        // tab === 9
        if (e.which === 9) {
            this.setState({shouldTriggerBlur: true});
        }

        // enter === 13  space === 32

        let enterKey = 13;
        let activeOption = this.state.results[this.state.activeIndex];
        if (e.which === enterKey && this.state.isExists) {
            $$.utils.IsPC() && this.refs.INPUT && this.refs.INPUT.blur();
            this.props.sameTextTips && this.props.sameTextTips();
        }
        if (e.which === enterKey && activeOption) {
            this.setState({
                value: this.state.value.concat(this._parseSelectedOption(activeOption)),
                input: ''
            }, () => {
                this._onSelect(activeOption);
                this._onChange();
                this._filterOptions();
                this._updatePlaceholder();
            });
        }

        if (e.which === enterKey && this.state.value.length >= this.state.valueMaxCounts && this.state.input) {
            $$.utils.IsPC() && this.refs.INPUT && this.refs.INPUT.blur();
            this.props.warningTips && this.props.warningTips();
        }

        // backspace === 8
        if (e.which === 8 && this.state.input === '' && this.state.value.length > 0) {
            let lastOption = this.state.value[this.state.value.length - 1];
            this.setState({value: this.state.value.slice(0, this.state.value.length - 1)},
                () => {
                    this._onDelete(lastOption);
                    this._onChange();
                    this._filterOptions();
                    this._updatePlaceholder();
                }
            );
        }

        // up === 38
        if (e.which === 38 && this.state.results.length > 1) {

            this.setState({
                activeIndex: this.state.results.length > 1 && this.state.activeIndex === 0 ? this.state.results.length - 1 : this.state.activeIndex - 1
            });

        }

        // down === 40
        if (e.which === 40 && this.state.results.length > 1) {
            this.setState({
                activeIndex: this.state.results.length > 1 && this.state.activeIndex === this.state.results.length - 1 ? 0 : this.state.activeIndex + 1
            });
        }

    }

    renderLabel() {
        return (
            <label
                className={this.props.labelClassName ? this.props.labelClassName + ' label' : 'label'}>
                {this.props.label || 'default'}
            </label>
        )
    }


    render() {
        let classname = classnames({
            'ori-reselect2-root': true,
            'focus': this.state.focus,
            ' ': true
        });
        return (
            <div
                className={this.props.className ? classname + this.props.className : classname}
                ref="ROOT"
                onClick={this.handleRootClick.bind(this)}
                onMouseEnter={this.handleMouseEnter.bind(this)}
                onMouseLeave={this.handleMouseLeave.bind(this)}>
                {!this.props.isLabel ? '' : this.renderLabel()}
                {this.renderSelectedValues()}
                {(!!this.state.input || this.state.value.length > 0) && this.props.children}
                {
                    // this.state.showOptions && this.renderOptions()
                }

            </div>
        );
    }
}
